// Standard library includes
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <filesystem>
#include <chrono>
#include <cmath>
#include <fstream>
#include <sstream>
#include <glob.h>

// Project includes - order matters!
#include "Common.h"       // First, basic structures
#include "Config.h"       // Configuration
#include "RinexParser.h"  // RINEX parsing
#include "Preprocessor.h" // Data preprocessing
#include "STECCalculator.h" // STEC calculation
#include "VTECConverter.h"  // VTEC conversion
#include "SphericalHarmonic.h" // Spherical harmonic modeling
#include "DCBEstimator.h"    // DCB estimation
#include "IONEXWriter.h"     // IONEX output
#include "Utils.h"           // Utility functions

// Namespace for file operations
namespace fs = std::filesystem;

// 添加命令行解析函数
struct ProgramOptions {
    std::string obsFile;
    std::string navFile;
    std::string sp3File;
    bool usePreciseOrbit = false;
    int sphericalDegree = 8;
    double ionoHeight = 350.0;
    double minElevation = 10.0;
    std::string outputFile = "output.ionex";
    std::vector<std::string> gnssSystems;  // 要处理的GNSS系统
    CycleSlipMethod csMethod = CycleSlipMethod::All;
    WeightingMode weightMode = WeightingMode::Combined;
    bool mitigateMultipath = true;
    double multipathThreshold = 0.5;
    std::string obsFilePattern;
    std::string navFilePattern;
    std::string sp3FilePattern;
    int timeInterval = 7200; // 默认2小时
    int numThreads = 4;      // 默认4线程
    std::string outputDir = "./output";  // 输出目录
    std::string mappingFunction = "SLM"; // 默认使用单层模型
    bool enablePhaseAlignedSTEC = true;  // 默认启用相位对齐伪距水平的STEC计算
    int smoothingWindowSize = 30;        // 默认滑动窗口大小
};

// 从配置文件读取参数
bool loadConfigFromFile(const std::string& configFile, ProgramOptions& options) {
    std::ifstream file(configFile);
    if (!file.is_open()) {
        std::cerr << "无法打开配置文件: " << configFile << std::endl;
        return false;
    }
    
    std::string line;
    std::string currentSection;
    
    while (std::getline(file, line)) {
        // 去除前后空格
        line.erase(0, line.find_first_not_of(" \t"));
        line.erase(line.find_last_not_of(" \t") + 1);
        
        // 跳过空行和注释
        if (line.empty() || line[0] == '#') {
            continue;
        }
        
        // 处理节名
        if (line[0] == '[' && line[line.size() - 1] == ']') {
            currentSection = line.substr(1, line.size() - 2);
            continue;
        }
        
        // 处理键值对
        size_t pos = line.find('=');
        if (pos != std::string::npos) {
            std::string key = line.substr(0, pos);
            std::string value = line.substr(pos + 1);
            
            // 去除键值对的前后空格
            key.erase(0, key.find_first_not_of(" \t"));
            key.erase(key.find_last_not_of(" \t") + 1);
            value.erase(0, value.find_first_not_of(" \t"));
            value.erase(value.find_last_not_of(" \t") + 1);
            
            // 根据节名和键名设置选项
            if (currentSection == "General") {
                if (key == "num_threads") {
                    options.numThreads = std::stoi(value);
                } else if (key == "output_dir") {
                    options.outputDir = value;
                }
            } else if (currentSection == "RINEX") {
                if (key == "systems") {
                    // 解析GNSS系统
                    std::stringstream ss(value);
                    std::string system;
                    while (std::getline(ss, system, ',')) {
                        options.gnssSystems.push_back(system);
                    }
                } else if (key == "obs_files") {
                    options.obsFilePattern = value;
                } else if (key == "nav_files") {
                    options.navFilePattern = value;
                } else if (key == "sp3_files") {
                    options.sp3FilePattern = value;
                }
            } else if (currentSection == "Preprocessing") {
                if (key == "min_elevation") {
                    options.minElevation = std::stod(value);
                } else if (key == "cycle_slip_method") {
                    if (value == "GF") options.csMethod = CycleSlipMethod::GeometryFree;
                    else if (value == "MW") options.csMethod = CycleSlipMethod::MelbourneWubbena;
                    else if (value == "TD") options.csMethod = CycleSlipMethod::TimeDifference;
                    else if (value == "IR") options.csMethod = CycleSlipMethod::IonosphereRate;
                    else if (value == "TurboEdit") options.csMethod = CycleSlipMethod::TurboEdit;
                    else if (value == "ALL") options.csMethod = CycleSlipMethod::All;
                    else options.csMethod = CycleSlipMethod::None;
                }
            } else if (currentSection == "STEC") {
                if (key == "enable_phase_aligned") {
                    options.enablePhaseAlignedSTEC = (value == "true" || value == "1" || value == "yes");
                } else if (key == "smoothing_window_size") {
                    options.smoothingWindowSize = std::stoi(value);
                }
            } else if (currentSection == "VTEC") {
                if (key == "iono_height") {
                    options.ionoHeight = std::stod(value);
                } else if (key == "sh_degree") {
                    options.sphericalDegree = std::stoi(value);
                } else if (key == "time_interval") {
                    options.timeInterval = std::stoi(value);
                } else if (key == "mapping_function") {
                    options.mappingFunction = value;
                }
            } else if (currentSection == "IONEX") {
                if (key == "output_file") {
                    options.outputFile = value;
                }
            }
        }
    }
    
    return true;
}

// 获取匹配文件模式的文件列表
std::vector<std::string> getMatchingFiles(const std::string& pattern) {
    std::vector<std::string> files;
    
    // 使用glob获取匹配的文件
    glob_t glob_result;
    if (glob(pattern.c_str(), GLOB_TILDE, NULL, &glob_result) == 0) {
        for (size_t i = 0; i < glob_result.gl_pathc; ++i) {
            files.push_back(std::string(glob_result.gl_pathv[i]));
        }
    }
    globfree(&glob_result);
    
    return files;
}

// 将观测数据按时间分组
std::map<int, std::vector<GNSSObservation>> groupObservationsByEpoch(const std::vector<GNSSObservation>& observations, int intervalMinutes) {
    std::map<int, std::vector<GNSSObservation>> epochGroups;
    
    for (const auto& obs : observations) {
        // 计算观测时间所属的时段索引
        int epochIndex = static_cast<int>(obs.time / (intervalMinutes * 60));
        epochGroups[epochIndex].push_back(obs);
    }
    
    return epochGroups;
}

// 获取特定时段的时间信息
TimePoint getTimePointForEpoch(int epochIndex, int intervalMinutes) {
    // 计算时段的起始时间（UNIX时间戳）
    time_t epochTime = epochIndex * intervalMinutes * 60;
    
    // 转换为日历时间
    std::tm* tm = std::gmtime(&epochTime);
    
    // 填充TimePoint结构
    TimePoint timePoint;
    timePoint.year = tm->tm_year + 1900;
    timePoint.month = tm->tm_mon + 1;
    timePoint.day = tm->tm_mday;
    timePoint.hour = tm->tm_hour;
    timePoint.minute = tm->tm_min;
    timePoint.second = 0;  // 简化处理，秒数设为0
    
    return timePoint;
}

// 分析指定时间间隔的电离层活动
void processIonosphereAtTimeIntervals(const std::vector<GNSSObservation>& observations,
                                     double ionoHeight, int sphericalDegree,
                                     double intervalsMinutes, const std::string& outputFile,
                                     const std::string& mappingFunction = "SLM",
                                     bool enablePhaseAlignedSTEC = true,
                                     int smoothingWindowSize = 30) {
    // 获取Config单例并设置参数
    auto& config = Config::getInstance();
    
    // 设置STEC计算参数
    config.stecSettings.enablePhaseAlignedSTEC = enablePhaseAlignedSTEC;
    config.stecSettings.smoothingWindowSize = smoothingWindowSize;
    
    // 设置VTEC转换参数
    config.vtecSettings.setMappingFunctionType(mappingFunction);
    config.vtecSettings.ionosphereHeight = ionoHeight;
    
    // STEC计算器
    STECCalculator stecCalc;
    stecCalc.setIonosphereHeight(ionoHeight);
    stecCalc.setMappingFunction(mappingFunction);  // 设置映射函数类型
    
    // 计算STEC：基于周跳标志划分弧段，使用相位观测值对齐到伪距水平
    std::cout << "计算STEC: 基于周跳标志划分弧段，使用相位观测值对齐到伪距水平..." << std::endl;
    auto stecObs = stecCalc.calculateSTEC(observations);
    std::cout << "计算得到STEC观测: " << stecObs.size() << " 条记录" << std::endl;
    
    // 将STEC转换为VTEC
    auto vtecObs = stecCalc.convertSTECToVTEC(stecObs);
    std::cout << "转换得到VTEC观测: " << vtecObs.size() << " 条记录" << std::endl;
    std::cout << "使用映射函数: " << mappingFunction << std::endl;
    
    // 按时间分组STEC观测
    int timeIntervalSeconds = static_cast<int>(intervalsMinutes * 60);
    auto timeGroups = stecCalc.groupSTECByTime(stecObs, timeIntervalSeconds);
    std::cout << "按时间分组: 共 " << timeGroups.size() << " 个时间段" << std::endl;
    
    // 存储每个时段的结果
    std::map<int, std::vector<double>> shCoeffsByTime;
    std::map<int, std::map<std::string, double>> satDCBsByTime;
    std::map<int, std::map<std::string, double>> recDCBsByTime;
    
    // 处理每个时间段
    for (const auto& [timeIndex, timeStecObs] : timeGroups) {
        if (timeStecObs.size() < 100) {  // 观测太少则跳过
            std::cout << "时间段 " << timeIndex << " 的观测数量不足，跳过" << std::endl;
            continue;
        }
        
        std::cout << "处理时间段 " << timeIndex << "，观测数量: " << timeStecObs.size() << std::endl;
        
        // 转换为VTEC
        std::vector<VTECObservation> timeVtecObs;
        for (const auto& stec : timeStecObs) {
            // 计算映射函数
            double mappingFunc = stecCalc.calculateMappingFunction(stec.elevation);
            
            // 创建VTEC观测
            VTECObservation vtec;
            vtec.time = stec.time;
            vtec.satellite = stec.satellite;
            vtec.station = stec.station;
            vtec.latitude = stec.latitude;
            vtec.longitude = stec.longitude;
            vtec.elevation = stec.elevation;
            vtec.azimuth = stec.azimuth;
            vtec.stec = stec.stec;
            vtec.mappingFunction = mappingFunc;
            vtec.vtec = stec.stec / mappingFunc;
            
            timeVtecObs.push_back(vtec);
        }
        
        // 使用联合估计方法同时估计VTEC球谐系数和DCB
        DCBEstimator jointEstimator;
        jointEstimator.setObservations(timeVtecObs);
        jointEstimator.setZeroMeanConstraint(true);
        jointEstimator.estimateVTECAndDCB(sphericalDegree);
        
        // 保存球谐系数
        shCoeffsByTime[timeIndex] = jointEstimator.getSphericalHarmonicCoefficients();
        
        // 保存DCB结果
        satDCBsByTime[timeIndex] = jointEstimator.getSatelliteDCBMap();
        recDCBsByTime[timeIndex] = jointEstimator.getReceiverDCBMap();
        
        // 验证结果，创建一个球谐模型用于可视化或其他目的（如需要）
        SphericalHarmonic shModel(sphericalDegree);
        shModel.setCoefficients(jointEstimator.getSphericalHarmonicCoefficients());
    }
    
    // 保存为IONEX文件
    IONEXWriter ionexWriter;
    ionexWriter.createIONEXFile(outputFile);
    
    // 设置时间和系数
    for (const auto& [timeIndex, coeffs] : shCoeffsByTime) {
        TimePoint timePoint = getTimePointForEpoch(timeIndex, intervalsMinutes);
        ionexWriter.addEpoch(timePoint, coeffs, satDCBsByTime[timeIndex], recDCBsByTime[timeIndex]);
    }
    
    // 完成IONEX文件写入
    ionexWriter.finalizeIONEXFile();
    std::cout << "IONEX文件写入完成：" << outputFile << std::endl;
}

int main(int argc, char* argv[]) {
    try {
        std::cout << "电离层VTEC估计与DCB解算程序" << std::endl;
        
        // 初始化程序选项
        ProgramOptions options;
        options.timeInterval = 7200; // 默认2小时
        options.numThreads = 4;      // 默认4线程
        
        // 默认配置文件
        std::string configFile = "config/default_config.ini";
        bool useConfigFile = false;
        
        // 检查是否指定了配置文件
        for (int i = 1; i < argc; ++i) {
            std::string arg = argv[i];
            if (arg == "--config" && i + 1 < argc) {
                configFile = argv[i + 1];
                useConfigFile = true;
                break;
            }
        }
        
        // 从配置文件加载选项
        if (useConfigFile) {
            if (loadConfigFromFile(configFile, options)) {
                std::cout << "已加载配置文件: " << configFile << std::endl;
            } else {
                std::cerr << "无法加载配置文件，使用默认配置" << std::endl;
            }
        }
        
        // 解析命令行参数(覆盖配置文件)
        for (int i = 1; i < argc; ++i) {
            std::string arg = argv[i];
            
            // 跳过配置文件参数
            if (arg == "--config" && i + 1 < argc) {
                ++i;
                continue;
            }
            
            // 处理其他命令行选项
            if (arg == "--obs" && i + 1 < argc) {
                options.obsFilePattern = argv[++i];
            } else if (arg == "--nav" && i + 1 < argc) {
                options.navFilePattern = argv[++i];
            } else if (arg == "--sp3" && i + 1 < argc) {
                options.sp3FilePattern = argv[++i];
            } else if (arg == "--degree" && i + 1 < argc) {
                options.sphericalDegree = std::stoi(argv[++i]);
            } else if (arg == "--iono-height" && i + 1 < argc) {
                options.ionoHeight = std::stod(argv[++i]);
            } else if (arg == "--min-elev" && i + 1 < argc) {
                options.minElevation = std::stod(argv[++i]);
            } else if (arg == "--output" && i + 1 < argc) {
                options.outputFile = argv[++i];
            } else if (arg == "--system" && i + 1 < argc) {
                options.gnssSystems.clear();
                std::string systems = argv[++i];
                for (char c : systems) {
                    if (c == 'G' || c == 'R' || c == 'E' || c == 'C' || c == 'J') {
                        options.gnssSystems.push_back(std::string(1, c));
                    }
                }
            } else if (arg == "--cs-method" && i + 1 < argc) {
                options.csMethod = static_cast<CycleSlipMethod>(std::stoi(argv[++i]));
            } else if (arg == "--weight-mode" && i + 1 < argc) {
                options.weightMode = static_cast<WeightingMode>(std::stoi(argv[++i]));
            } else if (arg == "--multipath") {
                options.mitigateMultipath = true;
            } else if (arg == "--no-multipath") {
                options.mitigateMultipath = false;
            } else if (arg == "--time-interval" && i + 1 < argc) {
                options.timeInterval = std::stoi(argv[++i]);
            } else if (arg == "--mapping-function" && i + 1 < argc) {
                options.mappingFunction = argv[++i];
            } else if (arg == "--phase-aligned") {
                options.enablePhaseAlignedSTEC = true;
            } else if (arg == "--no-phase-aligned") {
                options.enablePhaseAlignedSTEC = false;
            } else if (arg == "--smoothing-window" && i + 1 < argc) {
                options.smoothingWindowSize = std::stoi(argv[++i]);
            } else if (arg == "--help") {
                std::cout << "Usage: " << argv[0] << " [options]" << std::endl;
                std::cout << "Options:" << std::endl;
                std::cout << "  --config <file>        Load configuration from file (default: config/default_config.ini)" << std::endl;
                std::cout << "  --obs <file>           Observation file or pattern" << std::endl;
                std::cout << "  --nav <file>           Navigation file or pattern" << std::endl;
                std::cout << "  --sp3 <file>           Use precise orbit file or pattern" << std::endl;
                std::cout << "  --degree <n>           Spherical harmonic degree (default: 8)" << std::endl;
                std::cout << "  --iono-height <km>     Ionosphere shell height (default: 350km)" << std::endl;
                std::cout << "  --min-elev <deg>       Minimum elevation angle (default: 10°)" << std::endl;
                std::cout << "  --output <file>        Output IONEX file (default: output.ionex)" << std::endl;
                std::cout << "  --system <s>           GNSS system to process (G/R/E/C/empty for all)" << std::endl;
                std::cout << "  --cs-method <method>   Cycle slip detection method (0=None, 1=GF, 2=MW, 3=TD, 4=IR, 5=TurboEdit, 6=All)" << std::endl;
                std::cout << "  --weight-mode <mode>   Observation weighting mode (0=Uniform, 1=Elevation, 2=SNR, 3=Multipath, 4=Combined)" << std::endl;
                std::cout << "  --multipath            Enable multipath detection/mitigation (default)" << std::endl;
                std::cout << "  --no-multipath         Disable multipath detection/mitigation" << std::endl;
                std::cout << "  --time-interval <sec>  Time interval for VTEC maps in seconds (default: 7200)" << std::endl;
                std::cout << "  --mapping-function <f> Mapping function to use (SLM, MSLM, TSM, default: SLM)" << std::endl;
                std::cout << "  --phase-aligned        Use phase-aligned STEC calculation (default)" << std::endl;
                std::cout << "  --no-phase-aligned     Disable phase-aligned STEC calculation" << std::endl;
                std::cout << "  --smoothing-window <n> Smoothing window size for phase alignment (default: 30)" << std::endl;
                return 0;
            } else if (arg[0] != '-' && options.obsFilePattern.empty()) {
                // 如果是位置参数且观测文件模式为空，则设置为观测文件
                options.obsFilePattern = arg;
            } else if (arg[0] != '-' && options.navFilePattern.empty()) {
                // 如果是位置参数且导航文件模式为空，则设置为导航文件
                options.navFilePattern = arg;
            }
        }
        
        // 检查必要的文件模式是否已设置
        if (options.obsFilePattern.empty()) {
            throw std::runtime_error("未指定观测文件或模式，请使用--obs选项或在配置文件中设置");
        }
        
        if (options.navFilePattern.empty()) {
            throw std::runtime_error("未指定导航文件或模式，请使用--nav选项或在配置文件中设置");
        }
        
        // 获取匹配的观测文件
        std::vector<std::string> obsFiles = getMatchingFiles(options.obsFilePattern);
        if (obsFiles.empty()) {
            throw std::runtime_error("未找到匹配的观测文件: " + options.obsFilePattern);
        }
        
        // 获取匹配的导航文件
        std::vector<std::string> navFiles = getMatchingFiles(options.navFilePattern);
        if (navFiles.empty()) {
            throw std::runtime_error("未找到匹配的导航文件: " + options.navFilePattern);
        }
        
        // 获取匹配的SP3文件(如果有)
        std::vector<std::string> sp3Files;
        if (!options.sp3FilePattern.empty()) {
            sp3Files = getMatchingFiles(options.sp3FilePattern);
        }
        
        std::cout << "找到 " << obsFiles.size() << " 个观测文件" << std::endl;
        std::cout << "找到 " << navFiles.size() << " 个导航文件" << std::endl;
        if (!sp3Files.empty()) {
            std::cout << "找到 " << sp3Files.size() << " 个SP3文件" << std::endl;
        }
        
        // 1. 解析RINEX文件
        RinexParser parser;
        
        // 解析观测文件
        for (const auto& obsFile : obsFiles) {
            if (!parser.parseObservationFile(obsFile)) {
                std::cerr << "警告: 无法解析观测文件: " << obsFile << std::endl;
            }
        }
        
        // 解析导航文件
        for (const auto& navFile : navFiles) {
            if (!parser.parseNavigationFile(navFile)) {
                std::cerr << "警告: 无法解析导航文件: " << navFile << std::endl;
            }
        }
        
        // 解析SP3文件(如果有)
        bool usePreciseOrbit = false;
        if (!sp3Files.empty()) {
            for (const auto& sp3File : sp3Files) {
                if (parser.parseSP3File(sp3File)) {
                    usePreciseOrbit = true;
                } else {
                    std::cerr << "警告: 无法解析SP3文件: " << sp3File << std::endl;
                }
            }
            
            if (usePreciseOrbit) {
                std::cout << "使用精密星历计算卫星位置" << std::endl;
                parser.useHighPrecisionOrbit(true);
            } else {
                std::cout << "精密星历解析失败，回退到广播星历" << std::endl;
            }
        }
        
        // 过滤观测数据
        std::vector<GNSSObservation> observations;
        if (!options.gnssSystems.empty()) {
            observations = parser.getObservationsBySystems(options.gnssSystems);
            std::cout << "过滤得到 " << options.gnssSystems.size() << " 系统的观测数据: " 
                      << observations.size() << " 条记录" << std::endl;
        } else {
            observations = parser.getObservations();
            std::cout << "获取所有观测数据: " << observations.size() << " 条记录" << std::endl;
        }
        
        // 2. 数据预处理
        Preprocessor preprocessor;
        preprocessor.setObservations(observations);
        
        // 设置周跳探测方法
        preprocessor.setCycleSlipMethod(options.csMethod);
        
        // 探测并修复周跳
        preprocessor.detectAndFixCycleSlips();
        
        // 探测并减轻多路径效应
        if (options.mitigateMultipath) {
            preprocessor.setMultipathThreshold(options.multipathThreshold);
            preprocessor.detectAndMitigateMultipath();
        }
        
        // 设置观测权重模式
        preprocessor.setWeightingMode(options.weightMode);
        preprocessor.computeObservationWeights();
        
        // 质量控制
        preprocessor.qualityControl(options.minElevation);
        
        auto processedObs = preprocessor.getProcessedObservations();
        std::cout << "预处理后的观测数据: " << processedObs.size() << " 条记录" << std::endl;
        
        // 使用新的处理函数进行时间间隔分析
        processIonosphereAtTimeIntervals(processedObs, options.ionoHeight, 
                                        options.sphericalDegree, 
                                        options.timeInterval / 60.0, // 转换为分钟
                                        options.outputFile,
                                        options.mappingFunction,
                                        options.enablePhaseAlignedSTEC,
                                        options.smoothingWindowSize);
    
    return 0;
        
    } catch (const std::exception& e) {
        std::cerr << "错误: " << e.what() << std::endl;
        return 1;
    }
}